﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace COC.Graphics
{
	class BillBoardComponent : IRenderComponent
	{
		private Effect BillBoardEffect;
		private VertexDeclaration VertexDecl;
		private Dictionary<Texture2D, List<VertexPositionTexture>> BillBoards = new Dictionary<Texture2D,List<VertexPositionTexture>>();
		
		//private Effect AxisAlignedBillBoardEffect;
		//private Dictionary<Texture2D, List<AxisAlignedBillBoardVert>> AABillBoards;

		public override void Initialize()
		{
			VertexElement[] ve = new VertexElement[] {
				new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
				new VertexElement(0, 12, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),
			};
			VertexDecl = new VertexDeclaration(CoCGame.Singleton.GraphicsDevice, ve);
			BillBoardEffect = CoCGame.Singleton.Content.Load<Effect>("Shaders/BillBoard");
			//AxisAlignedBillBoardEffect = CoCGame.Singleton.Content.Load<Effect>("AABillBoard");
		}

		public void DrawBillBoardAxisAligned(Vector3 position, Vector2 size, Texture2D tex, Vector3 right, Vector3 up)
		{
			if (!BillBoards.ContainsKey(tex))
			{
				BillBoards.Add(tex, new List<VertexPositionTexture>());
			}

			VertexPositionTexture[] bbvert = new VertexPositionTexture[] {
				new VertexPositionTexture(position - right + up, new Vector2(0, 0)),
				new VertexPositionTexture(position + right + up, new Vector2(1, 0)),
				new VertexPositionTexture(position - right - up, new Vector2(0, 1)),
				new VertexPositionTexture(position - right - up, new Vector2(0, 1)),
				new VertexPositionTexture(position + right + up, new Vector2(1, 0)),
				new VertexPositionTexture(position + right - up, new Vector2(1, 1)),
			};

			BillBoards[tex].AddRange(bbvert);
		}

		public void DrawBillBoard(Vector3 position, Vector2 size, Texture2D tex)
		{
			Vector3 right = CoCGame.Singleton.GameCamera.Right * size.X * 0.5f;
			Vector3 up = CoCGame.Singleton.GameCamera.Up * size.Y * 0.5f;

			DrawBillBoardAxisAligned(position, size, tex, right, up);
		}

		public override void Render()
		{
			GraphicsDevice device = CoCGame.Singleton.GraphicsDevice;

			BillBoardEffect.Begin(SaveStateMode.SaveState);
			BillBoardEffect.Parameters["matWVP"].SetValue(
				CoCGame.Singleton.GameCamera.MatViewProj);
			device.RenderState.AlphaBlendEnable = true;
			device.RenderState.SourceBlend = Blend.One;
			device.RenderState.DestinationBlend = Blend.One;
			device.VertexDeclaration = VertexDecl;
			foreach (EffectPass pass in BillBoardEffect.Techniques[0].Passes)
			{
				pass.Begin();
				foreach (Texture2D tex in BillBoards.Keys)
				{
					BillBoardEffect.Parameters["BBTexture"].SetValue(tex);
					device.DrawUserPrimitives<VertexPositionTexture>(
						PrimitiveType.TriangleList, BillBoards[tex].ToArray(), 0, BillBoards[tex].Count / 3);
				}
				pass.End();
			}
			device.RenderState.SourceBlend = Blend.SourceAlpha;
			device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
			device.RenderState.AlphaBlendEnable = false;

			BillBoardEffect.End();

			BillBoards.Clear();
		}

		public override void Dispose()
		{
			VertexDecl.Dispose();
		}
	}
}